﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace BaseUtils.Utils
{
    public class RateLimiter
    {
        private readonly TimeSpan _delay;
        private readonly TimeSpan _period;
        private CancellationTokenSource _debounceCts;
        private DateTime _lastExecution = DateTime.MinValue;
        private object _lock = new object();

        public RateLimiter(TimeSpan delay, TimeSpan period)
        {
            _delay = delay;
            _period = period;
            _debounceCts = new CancellationTokenSource();
        }

        /// <summary>
        /// 防抖
        /// </summary>
        /// <param name="action"></param>
        public void Debounce(Action action)
        {
            _debounceCts.Cancel();
            _debounceCts = new CancellationTokenSource();
            var token = _debounceCts.Token;

            Task.Delay(_delay, token)
                .ContinueWith(t =>
                {
                    if (!token.IsCancellationRequested)
                    {
                        action();
                    }
                }, TaskScheduler.Current);
        }

        /// <summary>
        /// 节流
        /// </summary>
        /// <param name="action"></param>
        public void Throttle(Action action)
        {
            lock (_lock)
            {
                var now = DateTime.Now;
                var timeSinceLastExecution = now - _lastExecution;
                if (timeSinceLastExecution >= _period)
                {
                    action();
                    _lastExecution = now;
                }
            }
        }
    }

}